
#include "linux/errno.h"
#include "linux/chr.h"
#include "linux/fs.h"
#include "linux/init.h"
#include "linux/printk.h"
#include "linux/platform_device.h"
#include "linux/mm.h"

struct page *page;

int test_mmap_open(struct inode *inode, struct file *filp)
{
    return 0;
}

void test_mmap_close(struct inode *inode, struct file *filp)
{

}


int test_mmap_fault(struct vm_area_struct *vma, void *vmf)
{
    return 0;
}


struct page* test_mmap_nopage(struct vm_area_struct *area, unsigned long address, int write_access)
{
    page = alloc_page(GFP_KERNEL);
    if (!page)
        return NULL;

    return page;
}

struct vm_operations_struct test_file_vm_ops = 
{
    .fault = test_mmap_fault,
    .nopage = test_mmap_nopage,
};

int test_mmap_mmap(struct file *filp, struct vm_area_struct *vma)
{
    vma->vm_flags = VM_LOCKED;
    
    vma->vm_ops = &test_file_vm_ops;
    
    return 0;
}

struct file_operations test_mmap_fops = 
{
    .open = test_mmap_open,
    .close = test_mmap_close,
    .mmap = test_mmap_mmap,
};

static int test_mmap_init_module(void)
{
    int ret;
    
    ret = register_chrdev(24, "test_mmap", &test_mmap_fops);
    if (ret < 0)
    {

    }

    ret = sys_mknod("/dev/test_mmap", S_IFCHR, 24);
    if (ret < 0)
    {

    }

    return 0;
}

static void test_mmap_exit_module(void)
{

}

module_init(test_mmap_init_module);
module_exit(test_mmap_exit_module);